// 当断网时，需要拦截请求，使用缓存的结果
// 对资源进行离线缓存 serviceWorker可以自定义缓存的内容
const CACHE_NAME = 'cache_v' + 2;
// 缓存的内容越多越容易出现问题
const CACHE_LIST = [
    '/',
    '/index.html',
    '/main.js',
    '/main.css',
    '/api/list',
    '/manifest.json',
    '/icon.png'
]

async function fetchAndSave(request) {
    const res = await fetch(request); // 数据流
    console.log(res);
    let resClone = res.clone(); // 为了保证不破坏原有的响应结果，clone一份响应
    const cache = await caches.open(CACHE_NAME);
    await cache.put(request, resClone); // 更新缓存
    return res;
}

// 核心就是拦截请求
self.addEventListener('fetch',  (e) => {
    // 如果是静态资源，不作拦截
    let url = new URL(e.request.url);
    if (url.origin !== self.origin) return ;
    //    web worker支持ajax，但是service worker不支持ajax

    // 缓存策略
    // 如果接口是不停变化的 讲数据更新到缓存中
    // 接口缓存
    if (e.target.url && e.target.url.includes('/api')) {
        console.log('is include:', e.target.url)
        return e.respondWith(fetchAndSave(e.request).catch(res => {
            return caches.match(e.request)
        }))
    }

    // 如果断网了，会抛出异常
    // 返回从缓存中拿到的响应
   e.respondWith(fetch(e.request).catch(res => {
       return caches.match(e.request)
   }))
})

/**
 * 预缓存
 * @returns {Promise<void>}
 */
async function preCache() {
    let cache = await caches.open(CACHE_NAME); // 创建一个缓存空间
    console.log('cache is:', cache);
    await cache.addAll(CACHE_LIST);
    await self.skipWaiting();
}

/**
 * 清除缓存
 * @returns {Promise<void>}
 */
async function clearCache() {
    let cacheKeys = await caches.keys();
    // 清理缓存，等待把所有的缓存都清理干净
    await Promise.all(cacheKeys.map(cache => {
        if (cache !== CACHE_NAME) {
            return caches.delete(cache);
        }
    }))
}

// 当serviceWorker安装的时候， 需要跳过等待
self.addEventListener('install', (e) => {
    console.log('install');
    // 预先将缓存列表的数据缓存
    // 等待promise执行完成
    e.waitUntil(preCache());
})

// serviceWorker不是立即生效，需要在下一次访问的时候才生效
self.addEventListener('activate', (e) => {
    e.waitUntil(Promise.all([clearCache(), self.clients.claim()])) // 激活后立刻让serviceWorker拥有控制权
})

// 监听push事件，浏览器推送
self.addEventListener('push', function (e) {
    console.log(e.data.text());
    // self.registertion.showNotification(e.data.text())
    self.registration.showNotification(e.data.text());
})